package whut.GA;

import org.apache.commons.math3.util.FastMath;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Justin on 2018-04-20
 */
public class GAUtility {
    public static final double M = 1e10; //小数部分
    public static final double N = 1e2; //整数部分;
    public static final int L = (int)(FastMath.log(2,M*N) + 0.5);//编码长度

//    public static List<Integer> doubles2BinaryArray(double[] value) {
//
////        return doubles2BinaryArrayH(value);
//    }
//
//    public static double[] binaryArray2Doubles(List<Integer> value) {
//
////        return binaryArray2DoublesD(value);
//    }

    public static List<Integer> doubles2BinaryArrayH(double[] value) {
        List<Integer> result = new ArrayList<>();
        for (double item : value) {
            String eValue = String.format("%.15e",item);
            String[] splitValue = eValue.split("e");
            double part1 = Double.valueOf(splitValue[0]);
            int part2 = Integer.valueOf(splitValue[1]);
            String srtValue = String.format("%H",part1);
            double a = Double.valueOf(srtValue);
//            String strPart1 = String.format("%.16f", part1)

                    ;
//            int dotPos = strPart1.indexOf('.');
//            strPart1 = strPart1.substring(0,dotPos) + strPart1.substring(dotPos + 1);
//            long longPart1 = Long.parseUnsignedLong(strPart1);
//            char[] binPart1 = Long.toUnsignedString(longPart1,2).toCharArray();
//            char[] binPart2 = Integer.toUnsignedString(part2,2).toCharArray();

            long longLoc = FastMath.round((N + item) * M);
            char[] binLoc = Long.toUnsignedString(longLoc,2).toCharArray();
            int m = binLoc.length;

            for (int i = 0; i < L - m; i++) {
                result.add(0);
            }
            for (char c : binLoc) {
                result.add(c - '0');
            }
        }
        return result;
    }

    public static List<Integer> doubles2BinaryArrayD(double[] value) {
        List<Integer> result = new ArrayList<>();
        for (double item : value) {
            // for debug
            if (FastMath.abs(item) > N) {
                System.err.println("doubles2BinaryArray : Value is too large");
                System.exit(-1);
            }

            String eValue = String.format("%.15e",item);

            long longLoc = FastMath.round((N + item) * M);
            char[] binLoc = Long.toUnsignedString(longLoc,2).toCharArray();
            int m = binLoc.length;

            for (int i = 0; i < L - m; i++) {
                result.add(0);
            }
            for (char c : binLoc) {
                result.add(c - '0');
            }
        }
        return result;
    }

    public static double[] binaryArray2DoublesD(List<Integer> value) {
        int m = value.size() / L;
        if (value.size() != m * L) {
            System.err.println("the length is not a multiple of " + L);
            System.exit(-1);
        }
        double[] result = new double[m];
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < value.size(); i++) {
            s.append(value.get(i));
        }

        for (int i = 0; i < m; i++) {
            int a = i * L;
            int b = (i + 1) * L;

            String subStr = s.substring(a, b);
            long sub = Long.parseUnsignedLong(subStr, 2);
            double d = (double) sub / (M * N);
            d = d - (int) d;
            result[i] = d * N;
        }
        return result;
    }
}